/**
 * @file wa_screen_erase.c
 *
 */

 /*********************
  *      INCLUDES
  *********************/
#include "wa_screen_erase.h"
#include "wa_mask_draw.h"
#include "wa_area.h"
#include "wa_wm.h"
#include "wa_malloc.h"
/*********************
*      DEFINES
*********************/

/**********************
*      TYPEDEFS
**********************/

/**********************
*  STATIC PROTOTYPES
**********************/

/**********************
*  STATIC VARIABLES
**********************/
static wa_ll top_screen_erase_ll;
/**********************
*      MACROS
**********************/

/**********************
*   GLOBAL FUNCTIONS
**********************/
/**
 * screen erase module init
 */
void wa_screen_erase_module_init(void)
{
	wa_ll_init(&top_screen_erase_ll, sizeof(wa_screen_erase));
}

/**
 * create a sreen erase
 * @param scr
 */
wa_screen_erase* wa_screen_erase_create(void)
{
	wa_screen_erase* scr;
	scr = wa_ll_add_head(&top_screen_erase_ll);
	if (scr == NULL)
	{
		return scr;
	}
	scr->rect.x1 = 0;
	scr->rect.y1 = 0;
	scr->rect.x2 = 0;
	scr->rect.y2 = 0;
	scr->unit_width = 0;
	scr->unit_height = 0;
	scr->erase_rate = 0;
	scr->reverse = wa_nok;
	scr->erase_func = NULL;
	return scr;
}

/**
 * delete a screen erase
 * @param scr
 */
void wa_screen_erase_del(wa_screen_erase* scr)
{
	scr->rect.x1 = 0;
	scr->rect.y1 = 0;
	scr->rect.x2 = 0;
	scr->rect.y2 = 0;
	scr->unit_width = 0;
	scr->unit_height = 0;
	scr->erase_rate = 0;
	scr->reverse = wa_nok;
	scr->erase_func = NULL;
	wa_ll_remove(&top_screen_erase_ll, (void*)scr);
	wa_free(scr);
}

/**
 * screen erase set it's area
 * @param scr
 * @param x
 * @param y
 * @param width
 * @param height
 */
void wa_screen_erase_set_area(wa_screen_erase* scr, int x, int y, int width, int height)
{
	scr->rect.x1 = x;
	scr->rect.y1 = y;
	wa_area_set_width(&(scr->rect), width);
	wa_area_set_height(&(scr->rect), height);
}

/**
 * screen erase set unit size
 * @param scr
 * @param width
 * @param height
 */
void wa_screen_erase_set_unit_size(wa_screen_erase* scr, int width, int height)
{
	scr->unit_width = width;
	scr->unit_height = height;
}

/**
 * screen erase set erase rate
 * @param scr
 * @param erase_rate
 */
void wa_screen_erase_set_erase_rate(wa_screen_erase* scr, uint32_t erase_rate)
{
	scr->erase_rate = erase_rate;
}

/**
 * screen erase set func
 * @param scr
 * @param func
 */
void wa_screen_erase_set_func(wa_screen_erase* scr, void(*func)(wa_screen_erase* scr))
{
	scr->erase_func = func;
}

/**
 * screen erase set reverse
 * @param scr
 * @param reverse
 */
void wa_screen_erase_set_reverse(wa_screen_erase* scr, wa_result reverse)
{
	scr->reverse = reverse;
}

/**
 * screen erase update to erase screen
 * @param scr
 */
void wa_screen_erase_update(wa_screen_erase* scr)
{
	wa_wm_update_redraw_rect(&(scr->rect));
}

/**
 * screen erase handle
 */
void wa_screen_erase_handle(void)
{
	wa_screen_erase* scr;
	wa_screen_erase* scr_next;
	scr = (wa_screen_erase*)wa_ll_get_head(&top_screen_erase_ll);
	while (scr != NULL)
	{
		if (scr->erase_func != NULL)
		{
			if (scr->erase_rate != 0)
			{
				scr->erase_func(scr);
			}
		}
		scr_next = (wa_screen_erase*)wa_ll_get_next(&top_screen_erase_ll, scr);
		scr = scr_next;
	}
}

/**
 * screen erase func blinds horizontal
 * @param scr
 */
void wa_screen_erase_func_blinds_horizontal(wa_screen_erase* scr)
{
	uint32_t h_cnt, v_cnt;
	uint32_t width, height;
	uint32_t x_start, y_start;
	uint32_t h, v, i, j;
	uint32_t earse_height;
	x_start = scr->rect.x1;
	y_start = scr->rect.y1;
	width = wa_area_get_width(&(scr->rect));
	height = wa_area_get_height(&(scr->rect));
	h_cnt = width / scr->unit_width;
	v_cnt = height / scr->unit_height;
	
	earse_height = scr->unit_height * scr->erase_rate / 1000;

	for (v = 0; v <= v_cnt; v++)
	{
		for (h = 0; h <= h_cnt; h++)
		{
			uint32_t x0, y0;
			x0 = h * scr->unit_width;
			y0 = v * scr->unit_height;
			if (h % 2 != 0)
			{
				if (scr->reverse == wa_nok)
				{
					for (i = 0; i < earse_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < scr->unit_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
				else
				{
					for (i = 0; i < earse_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < scr->unit_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + j, y0 + scr->unit_height - earse_height + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
			}
			else
			{
				if (scr->reverse == wa_ok)
				{
					for (i = 0; i < earse_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < scr->unit_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
				else
				{
					for (i = 0; i < earse_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < scr->unit_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0  + j, y0 + scr->unit_height - earse_height + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
			}
		}
	}
}

/**
 * screen erase func blinds vertical
 * @param scr
 */
void wa_screen_erase_func_blinds_vertical(wa_screen_erase* scr)
{
	uint32_t h_cnt, v_cnt;
	uint32_t width, height;
	uint32_t x_start, y_start;
	uint32_t h, v, i, j;
	uint32_t earse_width;
	x_start = scr->rect.x1;
	y_start = scr->rect.y1;
	width = wa_area_get_width(&(scr->rect));
	height = wa_area_get_height(&(scr->rect));
	h_cnt = width / scr->unit_width;
	v_cnt = height / scr->unit_height;

	earse_width = scr->unit_width * scr->erase_rate / 1000;

	for (v = 0; v <= v_cnt; v++)
	{
		for (h = 0; h <= h_cnt; h++)
		{
			uint32_t x0, y0;
			x0 = h * scr->unit_width;
			y0 = v * scr->unit_height;
			if (v % 2 != 0)
			{
				if (scr->reverse == wa_nok)
				{
					for (i = 0; i < scr->unit_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < earse_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
				else
				{
					for (i = 0; i < scr->unit_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < earse_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + scr->unit_width - earse_width + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
			}
			else
			{
				if (scr->reverse == wa_ok)
				{
					for (i = 0; i < scr->unit_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < earse_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
				else
				{
					for (i = 0; i < scr->unit_height; i++)
					{
						if (i >= y_start + height)
						{
							break;
						}
						for (j = 0; j < earse_width; j++)
						{
							if (j >= x_start + width)
							{
								break;
							}
							wa_mask_drawpoint(x0 + scr->unit_width - earse_width + j, y0 + i, &(scr->rect), WA_COLOR_BACKGROUND);
						}
					}
				}
			}
		}
	}
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
